import Foundation
import AVFoundation
import SwiftUI

struct ExportFolder: FileDocument{
    static var readableContentTypes: [UTType]=[.folder]
    let path: String
    init(path: String){
        self.path=path
    }
    init(configuration: ReadConfiguration) throws {
        self.path=configuration.file.filename!
    }
    func fileWrapper(configuration: WriteConfiguration) throws -> FileWrapper {
        return try FileWrapper(url: URL(filePath: path))
    }
}

enum ExportStatus{
    case notStarted
    case exporting(Int, Int, String)
    case finished
    case error(String)
}

struct ContentView: View{
    @State var handler=ExportHandler()
    @State var filePromptPresented=false
    
    func resetUI(){
        handler.status = .notStarted
        handler.displayItems=[]
    }
    
    var body: some View{
        // List view frame
        ScrollViewReader{proxy in 
            let fail: Binding<Bool> = Binding(get: {
                switch handler.status{
                case .error:
                    return true
                default:
                    return false
                }
            }, set: {state in
                if state{
                    handler.status = .error("")
                }else{
                    handler.status = .notStarted
                }
            })
            
            List(handler.displayItems){item in
                // List item view
                HStack{
                    // Status indicator
                    switch item.status {
                    case .inProgress:
                        ProgressView()
                    case .finished:
                        Image(systemName: "checkmark.circle")
                            .foregroundStyle(.green)
                    case .error:
                        Image(systemName: "xmark.circle")
                            .foregroundStyle(.red)
                    }
                    // Filenames and paths display
                    VStack(alignment: .leading, spacing: 4){
                        HStack(spacing: 3){
                            Image(systemName: "document")
                                .fontWeight(.semibold)
                            Text(item.source)
                        }
                        .foregroundStyle(.secondary)
                        .font(.footnote)
                        HStack(spacing: 4){
                            Image(systemName: "rectangle.portrait.and.arrow.right")
                                .foregroundStyle(.secondary)
                                .fontWeight(.semibold)
                                .font(.footnote)
                            Text(item.target)
                        }
                        HStack(spacing: 4){
                            Image(systemName: "music.note.list")
                                .fontWeight(.semibold)
                                .font(.footnote)
                            Text(item.title)
                        }
                        .foregroundStyle(.secondary)
                    }
                    .lineLimit(2)
                    .minimumScaleFactor(0.75)
                }
            }
            .onChange(of: handler.displayItems){
                withAnimation{
                    if let last=handler.displayItems.last{
                        proxy.scrollTo(last.id)
                    }
                }
            }
            .alert("Error", isPresented: fail, actions: {
                Button("OK", action: {handler.status = .notStarted})
            }, message: {
                if case .error(let msg) = handler.status{
                    Text("An error occurred: \(msg)")
                }else{
                    Text("Unknown error")
                }
            })
            .clipShape(.rect(cornerRadius: 15))
            .overlay{
                RoundedRectangle(cornerRadius: 15)
                    .stroke(Color.gray, lineWidth: 2)
            }
            .padding()
        }
        // Status display
        VStack{
            if /*ProcessInfo.processInfo.isMacCatalystApp ||*/ false{
                HStack{
                    Image(systemName: "xmark.circle")
                        .foregroundStyle(.red)
                    Text("You must run this script on iPad")
                }
                .padding(.vertical, 5)
            }
            else{
                // Text display
                HStack{
                    switch handler.status{
                    case let .exporting(finished, total, label):
                        ProgressView()
                        Text("Exporting \(label)... (\(finished)/\(total))")
                    case .finished:
                        Image(systemName: "checkmark.circle")
                            .foregroundStyle(.green)
                            .onLongPressGesture(minimumDuration: 0.5) { 
                                // Hold icon to reset UI
                                resetUI()
                            }
                        Text("Export complete")
                    default:
                        Text("Choose what to export:")
                    }
                }
                // Button/progress bar
                HStack{
                    switch handler.status{
                    case .notStarted, .error:
                        // Start buttons
                        ForEach(exportDirs){dir in
                            Button(action: {Task{await handler.export(dir)}})
                            {Label(dir.label, systemImage: "square.and.arrow.down.on.square")}
                                .padding()
                                .foregroundStyle(.white)
                                .background(Color.accentColor)
                                .clipShape(.capsule)
                        }
                    case let .exporting(finished, total, _):
                        ProgressView(value: Double(finished)/Double(total))
                            .padding()
                            .padding(.horizontal, 20)
                    case .finished:
                        // Save and share buttons
                        Group{
                            Button(action: {
                                let tmp=FileManager.default.temporaryDirectory.path+"/\(handler.tempDirName)"
                                // Need to remove temp dir created by share sheets
                                do{
                                    if FileManager.default.fileExists(atPath: tmp){
                                        try FileManager.default.removeItem(atPath: tmp)
                                    }
                                }catch{
                                    handler.status = .error(error.localizedDescription)
                                    return
                                }
                                filePromptPresented=true
                            }, label: {
                                Label("Save folder", systemImage: "square.and.arrow.down")
                            })
                            .fileExporter(isPresented: $filePromptPresented, document: ExportFolder(path: handler.tempDir), contentType: .folder, onCompletion: {result in 
                                if case .failure(let error) = result{
                                    handler.status = .error(error.localizedDescription)
                                }
                            })
                            ShareLink(item: URL(filePath: handler.tempDir)){
                                Label("Share folder", systemImage: "square.and.arrow.up")
                            }
                        }
                        .padding()
                        .foregroundStyle(.white)
                        .background(Color.blue)
                        .clipShape(.capsule)
                    }
                }
                .padding(.top, 10)
            }
        }
        .padding(.bottom, 25)
    }
}
